import aiohttp
import json
import asyncio
from typing import Dict, Any, Optional, List
from decimal import Decimal

from .ai_base import BaseAIService, GenerationRequest, GenerationResponse, AIServiceProvider, AIServiceType
from app.core.error_handler import robust_executor, with_retry

class GoogleVeo3Service(BaseAIService):
    """Google Veo 3 AI服务实现"""
    
    def __init__(self, config: Dict[str, Any]):
        super().__init__(config)
        self.api_key = config.get("api_key")
        self.project_id = config.get("project_id")  # Google Cloud项目ID
        self.location = config.get("location", "us-central1")  # API区域
        
        # API URLs - 这些是假设的URL，实际需要根据Google Veo 3文档调整
        self.base_url = f"https://{self.location}-aiplatform.googleapis.com/v1"
        self.video_generation_url = f"{self.base_url}/projects/{self.project_id}/locations/{self.location}/publishers/google/models/veo-3:generateContent"
        
        # Veo 3特殊配置
        self.max_duration = config.get("max_duration", 60)  # 最大视频时长(秒)
        self.default_resolution = config.get("default_resolution", "1280x720")
        self.default_fps = config.get("default_fps", 24)
    
    def get_provider_name(self) -> AIServiceProvider:
        return AIServiceProvider.GOOGLE_VEO3
    
    def get_supported_services(self) -> List[AIServiceType]:
        return [
            AIServiceType.VIDEO_GENERATION,
        ]
    
    async def generate_video(self, request: GenerationRequest) -> GenerationResponse:
        """生成视频内容 - 带错误处理和重试"""
        return await robust_executor.execute_with_retry(
            self._generate_video_internal,
            "google_veo3",
            request
        )
    
    async def _generate_video_internal(self, request: GenerationRequest) -> GenerationResponse:
        """内部视频生成方法"""
        try:
            # 构建请求参数
            payload = self._build_video_generation_payload(request)
            
            # 发送请求到Google Veo 3 API
            async with aiohttp.ClientSession() as session:
                headers = {
                    "Authorization": f"Bearer {await self._get_access_token()}",
                    "Content-Type": "application/json",
                    "X-Goog-User-Project": self.project_id
                }
                
                async with session.post(
                    self.video_generation_url,
                    headers=headers,
                    json=payload,
                    timeout=aiohttp.ClientTimeout(total=300)  # 5分钟超时
                ) as response:
                    
                    if response.status == 200:
                        result = await response.json()
                        return await self._process_video_generation_response(result, request)
                    elif response.status == 429:
                        # API限流错误
                        raise Exception("Rate limit exceeded - too many requests")
                    elif response.status == 401:
                        # 认证错误
                        raise Exception("Authentication failed - invalid credentials")
                    elif response.status == 403:
                        # 配额超限
                        raise Exception("Quota exceeded - insufficient credits")
                    elif response.status >= 500:
                        # 服务器错误
                        error_text = await response.text()
                        raise Exception(f"Service unavailable - server error {response.status}: {error_text}")
                    else:
                        error_text = await response.text()
                        raise Exception(f"Google Veo 3 API错误: {response.status} - {error_text}")
                        
        except asyncio.TimeoutError:
            raise Exception("Request timeout - Google Veo 3 generation took too long")
        except aiohttp.ClientError as e:
            raise Exception(f"Network error - connection failed: {str(e)}")
        except Exception as e:
            # 重新抛出，让错误处理器分类
            raise e
    
    def _build_video_generation_payload(self, request: GenerationRequest) -> Dict[str, Any]:
        """构建视频生成请求payload"""
        
        # 基础参数
        payload = {
            "contents": [{
                "role": "user",
                "parts": [{
                    "text": request.prompt
                }]
            }],
            "generationConfig": {
                "temperature": request.params.get("temperature", 0.7),
                "candidateCount": 1,
                "maxOutputTokens": request.params.get("max_tokens", 1000),
            },
            "safetySettings": [
                {
                    "category": "HARM_CATEGORY_HATE_SPEECH",
                    "threshold": "BLOCK_MEDIUM_AND_ABOVE"
                },
                {
                    "category": "HARM_CATEGORY_DANGEROUS_CONTENT",
                    "threshold": "BLOCK_MEDIUM_AND_ABOVE"
                },
                {
                    "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
                    "threshold": "BLOCK_MEDIUM_AND_ABOVE"
                },
                {
                    "category": "HARM_CATEGORY_HARASSMENT",
                    "threshold": "BLOCK_MEDIUM_AND_ABOVE"
                }
            ]
        }
        
        # Veo 3特定参数
        video_config = {
            "duration": min(request.params.get("duration", 10), self.max_duration),
            "resolution": request.params.get("resolution", self.default_resolution),
            "fps": request.params.get("fps", self.default_fps),
            "aspect_ratio": request.params.get("aspect_ratio", "16:9"),
            "style": request.params.get("style", "cinematic"),  # 电影风格
            "motion": request.params.get("motion", "medium"),   # 运动强度: low, medium, high
            "camera_movement": request.params.get("camera_movement", "static")  # 镜头运动
        }
        
        # 如果有源图片（图片转视频）
        if request.params.get("source_image_url"):
            # 这里需要异步处理，先标记
            video_config["mode"] = "image_to_video"
            video_config["source_image"] = request.params["source_image_url"]
        else:
            video_config["mode"] = "text_to_video"
        
        payload["video_config"] = video_config
        
        return payload
    
    async def _get_access_token(self) -> str:
        """获取Google Cloud访问令牌"""
        # 这里需要实现Google Cloud认证
        # 可以使用service account key或者其他认证方式
        # 简化示例，实际应该使用google-auth库
        
        try:
            # 如果配置了服务账号文件路径
            service_account_path = self.config.get("service_account_path")
            if service_account_path:
                from google.auth.transport.requests import Request
                from google.oauth2 import service_account
                
                credentials = service_account.Credentials.from_service_account_file(
                    service_account_path,
                    scopes=['https://www.googleapis.com/auth/cloud-platform']
                )
                
                credentials.refresh(Request())
                return credentials.token
            else:
                # 如果没有配置服务账号，使用API Key（某些API可能支持）
                return self.api_key
                
        except Exception as e:
            # 如果认证失败，使用API Key作为后备
            return self.api_key
    
    async def _process_video_generation_response(self, result: Dict[str, Any], request: GenerationRequest) -> GenerationResponse:
        """处理视频生成响应"""
        try:
            # Google Veo 3可能返回的响应结构（需要根据实际API调整）
            candidates = result.get("candidates", [])
            if not candidates:
                return GenerationResponse(
                    success=False,
                    error_message="Google Veo 3未返回生成结果"
                )
            
            candidate = candidates[0]
            
            # 检查是否有安全性问题
            if candidate.get("finishReason") == "SAFETY":
                return GenerationResponse(
                    success=False,
                    error_message="内容被安全过滤器阻止，请调整提示词"
                )
            
            # 提取视频URL或Base64数据
            content = candidate.get("content", {})
            parts = content.get("parts", [])
            
            video_url = None
            
            for part in parts:
                if "video" in part:
                    video_url = part["video"].get("url")  # 视频URL
                elif "video_url" in part:
                    video_url = part["video_url"]  # 直接的视频URL
            
            if not video_url:
                return GenerationResponse(
                    success=False,
                    error_message="未找到生成的视频URL"
                )
            
            # 构建成功响应
            response = GenerationResponse(
                success=True,
                result_url=video_url,
                metadata={
                    "duration": request.params.get("duration", 10),
                    "resolution": request.params.get("resolution", self.default_resolution),
                    "fps": request.params.get("fps", self.default_fps),
                    "provider": "google_veo3",
                    "model": "veo-3",
                    "generation_time": result.get("generation_time"),
                    "usage": result.get("usage", {})
                },
                cost=self.calculate_cost(request)
            )
            
            return response
            
        except Exception as e:
            return GenerationResponse(
                success=False,
                error_message=f"处理Google Veo 3响应失败: {str(e)}"
            )
    
    async def generate_image(self, request: GenerationRequest) -> GenerationResponse:
        """Veo 3主要专注于视频生成，图片生成可以调用其他服务"""
        return GenerationResponse(
            success=False,
            error_message="Google Veo 3专注于视频生成，图片生成请使用其他服务"
        )
    
    async def edit_image(self, request: GenerationRequest, image_url: str) -> GenerationResponse:
        """图片编辑不支持"""
        return GenerationResponse(
            success=False,
            error_message="Google Veo 3不支持图片编辑功能"
        )
    
    async def face_swap(self, request: GenerationRequest, source_url: str, target_url: str) -> GenerationResponse:
        """人脸替换不支持"""
        return GenerationResponse(
            success=False,
            error_message="Google Veo 3不支持人脸替换功能"
        )
    
    async def get_task_status(self, task_id: str):
        """获取任务状态（Veo 3可能是同步的，但也可能有异步任务）"""
        return await robust_executor.execute_with_retry(
            self._get_task_status_internal,
            "google_veo3_status",
            task_id
        )
    
    async def _get_task_status_internal(self, task_id: str) -> str:
        """内部任务状态查询方法"""
        try:
            # 如果Google Veo 3提供异步任务状态查询API
            status_url = f"{self.base_url}/projects/{self.project_id}/locations/{self.location}/operations/{task_id}"
            
            async with aiohttp.ClientSession() as session:
                headers = {
                    "Authorization": f"Bearer {await self._get_access_token()}",
                    "X-Goog-User-Project": self.project_id
                }
                
                async with session.get(
                    status_url,
                    headers=headers,
                    timeout=aiohttp.ClientTimeout(total=30)
                ) as response:
                    
                    if response.status == 200:
                        result = await response.json()
                        # 根据Google Cloud Operations API格式解析状态
                        if result.get("done", False):
                            if "error" in result:
                                return "failed"
                            else:
                                return "completed"
                        else:
                            return "processing"
                    elif response.status == 404:
                        return "not_found"
                    else:
                        raise Exception(f"Status query failed: {response.status}")
        
        except Exception as e:
            # 如果状态查询失败，默认为完成状态
            # 这适用于同步API或状态查询不可用的情况
            return "completed"
    
    def validate_config(self) -> bool:
        """验证配置是否正确"""
        try:
            required_fields = ["api_key", "project_id"]
            for field in required_fields:
                if not self.config.get(field):
                    return False
            
            # 验证其他配置参数的有效性
            if self.max_duration <= 0:
                return False
            
            # 验证location格式
            if not self.location or not isinstance(self.location, str):
                return False
            
            return True
        except Exception:
            return False
    
    def calculate_cost(self, request: GenerationRequest) -> float:
        """估算成本（需要根据Google Veo 3的实际定价调整）"""
        try:
            # 假设的定价模型（调整为演示友好的价格）
            base_cost = 0.20  # 基础成本
            duration = request.params.get("duration", 10)
            
            # 确保duration是有效的数值
            if not isinstance(duration, (int, float)) or duration <= 0:
                duration = 10
            
            # 分辨率成本倍数
            resolution = request.params.get("resolution", "1280x720")
            resolution_multiplier = {
                "640x480": 1.0,
                "1280x720": 1.2,
                "1920x1080": 1.5,
                "3840x2160": 2.5  # 4K
            }.get(resolution, 1.2)
            
            # 风格和运动强度可能影响计算成本
            style_multiplier = 1.0
            if request.params.get("style") == "cinematic":
                style_multiplier = 1.2
            
            motion_multiplier = {
                "low": 1.0,
                "medium": 1.1,
                "high": 1.3
            }.get(request.params.get("motion", "medium"), 1.1)
            
            # 图片转视频可能需要额外成本
            mode_multiplier = 1.2 if request.params.get("source_image_url") else 1.0
            
            total_cost = (base_cost * duration * resolution_multiplier * 
                         style_multiplier * motion_multiplier * mode_multiplier)
            
            return round(total_cost, 2)
            
        except Exception as e:
            # 如果成本计算失败，返回默认成本
            return 2.0  # 默认估算成本